package com;
/*
* java 引用变量有两个类型：编译时类型：由声明该变量时使用的类型决定运行时类型：由实际赋给该变量的对象决定
*
* 作用：屏蔽不同子类或实现类之间的实现差异，从而可以做到通用编程
*
* 注意：
*   - 只有实例方法才有多态效果（调用子类的实例方法）， 类方法和字段都没有（访问父类字段或调用时父类方法）
*   - 编译时会检查父类（编译时类型） 是否存在该实例方法，若不存在会编译报错；运行时先从子类（运行时类型）找到实例方法，找到就执行，没找到就去父类里面找
*
* 当对象有多重形态，需要调用只存子类的实例方法时，可以对该引用变量进行强制类型转换
* */

class  People{
    String name = "alex";
    public void super_method(){
        System.out.println("父类中普通的实例方法！！！");
    }

    public void test(){
        System.out.println("父类中被覆盖的实例方法！！！");
    }

    public void say(){}
}

class Man extends People{
    String name = "Jack";

    public void sub_method(){
        System.out.println("子类的普通实例方法！！！");
    }

    @Override
    public void test(){
        System.out.println("子类中覆盖父亲的实例方法！！！");
    }

    public void say(){
        System.out.println("I'm man!!!");
    }

}

class WoMan extends People{
    public void say(){
        System.out.println("I'm woman!!!");
    }
}

public class class_polymorphism {
    public static void main(String[] args) {
        //
        People m = new Man();
        System.out.println(m.name);  // 父类实例变量              alex
        System.out.println(((Man)m).name); // 子类实例变量：      Jack
        m.super_method();// 父类中普通的实例方法
        m.test(); // 子类中覆盖父类的实例方法
        //m.sub_method();//  error ,   People中没有sub_method();
        ((Man)m).sub_method(); // 子类中普通的实例方法
    }
}

//    // 向上转型：把子类对象赋给父类引用变量（多态）
//    Animal a = new Dog();
//    Object obj = new Dog();
//    // 强制类型转换：把父类对象赋给子类引用变量
//    Dog d = (Dog) a;
//    Cat c1 = (Cat) a; // ClassCastException: Dog cannot be cast to Cat
//    Cat c2 = (Cat) new Animal(); // ClassCastException


// 在进行强制类型转换之前，先用 instanceof 运算符判断是否可以成功转换，从而避免出现 ClassCastException 异常
//if (a instanceof Dog) {
//        Dog d = (Dog) a;
//        }
